/* 文件： w25flash.h
 * 功能描述： Flash 存储器W25Q128的驱动程序
 * 作者：王维波
 * 修改日期：2019-06-05
 * W25Q128 芯片参数： 16M字节，24位地址线
 * 分为256个Block，每个Block 64K字节
 * 一个Block又分为16个Sector，共4096个Sector，每个Sector 4K字节
 * 一个Sector又分为16个Page，共65536个Page，每个Page 256字节
 * 写数据操作的基本单元是Page，一次连续写入操作不能超过一个Page的范围。写的Page必须是擦除过的。
 */

#ifndef _W25FLASH_H
#define _W25FLASH_H

//#include 	"stm32f4xx_hal.h"
#include	"spi.h"		//使用其中的变量 hspi1，表示SPI1接口
#include "main.h"
/*  W25Q128硬件接口相关的部分：CS引脚和SPI接口 ，若电路不同，更改这部分配置即可   */
/* NORFLASH 片选信号 */
#define NORFLASH_CS(x)      do{ x ? \
                                  HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET); \
                            }while(0)

/**
* 对于 25Q256 FLASH 芯片, 我们规定前 25M 给 FATFS 使用, 25M 以后
* 紧跟字库, 4 个字库 + UNIGBK.BIN, 总大小 6.01M, 共占用 31.01M
* 31.01M 以后的存储空间大家可以随便使用.
*/
//=========== Flash存储芯片 W25Q32 的存储容量参数（适配 FatFS）================
#define SPI_FLASH_SECTOR_SIZE    4096    /* W25Q32 物理扇区大小：4KB */
#define SPI_FLASH_SECTOR_COUNT   1024    /* W25Q32 总扇区数：4MB ÷ 4KB = 1024 */
#define SPI_FLASH_BLOCK_SIZE     8       /* W25Q32 擦除块大小：1个Block=8个扇区 */
#define SPI_FLASH_FATFS_BASE     0       /* FatFS 起始地址：从 Flash 0 地址开始 */

//#define		FLASH_PAGE_SIZE			256		//一个Page是256字节
//#define		FLASH_SECTOR_SIZE		4096	//一个Sector是4096字节
//#define		FLASH_SECTOR_COUNT		4096	//总共4096个 Sector

/* FLASH芯片列表 */
#define W25Q80      0XEF13          /* W25Q80   芯片ID */
#define W25Q16      0XEF14          /* W25Q16   芯片ID */
#define W25Q32      0XEF15          /* W25Q32   芯片ID */
#define W25Q64      0XEF16          /* W25Q64   芯片ID */
#define W25Q128     0XEF17          /* W25Q128  芯片ID */
#define W25Q256     0XEF18          /* W25Q256  芯片ID */
#define BY25Q64     0X6816          /* BY25Q64  芯片ID */
#define BY25Q128    0X6817          /* BY25Q128 芯片ID */
#define BY25Q256    0X6818          /* BY25Q256 芯片ID */
#define NM25Q64     0X5216          /* NM25Q64  芯片ID */
#define NM25Q128    0X5217          /* NM25Q128 芯片ID */
/* 指令表 */
#define FLASH_WriteEnable           0x06
#define FLASH_WriteDisable          0x04
#define FLASH_ReadStatusReg1        0x05
#define FLASH_ReadStatusReg2        0x35
#define FLASH_ReadStatusReg3        0x15
#define FLASH_WriteStatusReg1       0x01
#define FLASH_WriteStatusReg2       0x31
#define FLASH_WriteStatusReg3       0x11
#define FLASH_ReadData              0x03
#define FLASH_FastReadData          0x0B
#define FLASH_FastReadDual          0x3B
#define FLASH_FastReadQuad          0xEB
#define FLASH_PageProgram           0x02
#define FLASH_PageProgramQuad       0x32
#define FLASH_BlockErase            0xD8
#define FLASH_SectorErase           0x20
#define FLASH_ChipErase             0xC7
#define FLASH_PowerDown             0xB9
#define FLASH_ReleasePowerDown      0xAB
#define FLASH_DeviceID              0xAB
#define FLASH_ManufactDeviceID      0x90
#define FLASH_JedecDeviceID         0x9F
#define FLASH_Enable4ByteAddr       0xB7
#define FLASH_Exit4ByteAddr         0xE9
#define FLASH_SetReadParam          0xC0
#define FLASH_EnterQPIMode          0x38
#define FLASH_ExitQPIMode           0xFF

extern uint16_t norflash_TYPE;      /* 定义FLASH芯片型号 */

/******************************************************************************************/

/* 静态函数 */
static void norflash_wait_busy(void);                                               /* 等待空闲 */
static void norflash_send_address(uint32_t address);                                /* 发送地址 */
static void norflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen);    /* 写入page */
static void norflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen); /* 写flash,不带擦除 */

/* 普通函数 */
void spi_stability_test(void);
void norflash_init(void);                                                           /* 初始化25QXX */
uint16_t norflash_read_id(void);                                                    /* 读取FLASH ID */
void norflash_write_enable(void);                                                   /* 写使能 */
uint8_t norflash_read_sr(uint8_t regno);                                            /* 读取状态寄存器 */
void norflash_write_sr(uint8_t regno, uint8_t sr);                                  /* 写状态寄存器 */

void norflash_erase_chip(void);                                                     /* 整片擦除 */
void norflash_erase_sector(uint32_t saddr);                                         /* 扇区擦除 */
void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen);                 /* 读取flash */
void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen);                /* 写入flash */

#endif
